Newer
Older
BlackoutClient / Assets / Best HTTP / Source / Extensions / ReadOnlyBufferedStream.cs
using BestHTTP.PlatformSupport.Memory;
using System;
using System.IO;

namespace BestHTTP.Extensions
{
    public sealed class ReadOnlyBufferedStream : Stream
    {
        Stream stream;
        public const int READBUFFER = 8192;
        byte[] buf;
        int available = 0;
        int pos = 0;

        public ReadOnlyBufferedStream(Stream nstream)
            :this(nstream, READBUFFER)
        {
        }

        public ReadOnlyBufferedStream(Stream nstream, int bufferSize)
        {
            stream = nstream;
            buf = BufferPool.Get(bufferSize, true);
        }

        public override int Read(byte[] buffer, int offset, int size)
        {
            if (size <= available)
            {
                Array.Copy(buf, pos, buffer, offset, size);
                available -= size;
                pos += size;
                return size;
            }
            else
            {
                int readcount = 0;
                if (available > 0)
                {
                    Array.Copy(buf, pos, buffer, offset, available);
                    offset += available;
                    readcount += available;
                    available = 0;
                    pos = 0;
                }

                while (true)
                {
                    try
                    {
                        available = stream.Read(buf, 0, buf.Length);
                        pos = 0;
                    }
                    catch (Exception ex)
                    {
                        if (readcount > 0)
                        {
                            return readcount;
                        }

                        throw (ex);
                    }
                    if (available < 1)
                    {
                        if (readcount > 0)
                        {
                            return readcount;
                        }

                        return 0;
                    }
                    else
                    {
                        int toread = size - readcount;
                        if (toread <= available)
                        {
                            Array.Copy(buf, pos, buffer, offset, toread);
                            available -= toread;
                            pos += toread;
                            readcount += toread;
                            return readcount;
                        }
                        else
                        {
                            Array.Copy(buf, pos, buffer, offset, available);
                            offset += available;
                            readcount += available;
                            pos = 0;
                            available = 0;
                        }
                    }
                }
            }
        }

        public override int ReadByte()
        {
            if (available > 0)
            {
                available -= 1;
                pos += 1;
                return buf[pos - 1];
            }
            else
            {
                try
                {
                    available = stream.Read(buf, 0, buf.Length);
                    pos = 0;
                }
                catch
                {
                    return -1;
                }
                if (available < 1)
                {
                    return -1;
                }
                else
                {
                    available -= 1;
                    pos += 1;
                    return buf[pos - 1];
                }
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (buf != null)
                BufferPool.Release(buf);

            buf = null;
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { throw new NotImplementedException(); }
        }

        public override bool CanWrite
        {
            get { throw new NotImplementedException(); }
        }

        public override long Length
        {
            get { throw new NotImplementedException(); }
        }

        public override long Position
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public override void Flush()
        {
            throw new NotImplementedException();
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotImplementedException();
        }
    }
}